#include "power.h"

#if USE_POWER_MODULE
#include <stdint.h>
#include "../../board.h"
#include "power_charger.h"
#include "power_nvm.h"
#include "lvgl/lvgl.h"

//#define printf cplog_printf
#define For_Watch_Battery   1

/* Timeouts */
#define HAL_TICK1S 1000
#define MS_WAITING      *HAL_TICK1S / 1000
volatile uint32_t Time_To_MMI_Evt = 0;
#define PM_FILTRATE_BATTERY_STEP    800

#define PM_RF_TX_BATTERY_STEP       120

/* Number of steps for the MEAN calculation */
#define PM_AVERAGE_BATTERY_NB       32
/* change threshold needed for stable value update */
/* 10 mV is 1% with current battery technology */
#define PM_HYSTERESIS_BATTERY_STEP  50
#define PM_HYSTERESIS_BATTERY_PERCENT_EDGE 7
/*/ delay between battery monitoring during IDLE */
#define PM_BAT_MONITOR_IDLE_TIME         15 * HAL_TICK1S/*1 * 60 * HAL_TICK1S */
/*/ delay between battery monitoring during CALL */
#define PM_BAT_MONITOR_CALL_TIME         5 * HAL_TICK1S
/*/ delay between battery monitoring during IDLE with low battery */
#define PM_BAT_MONITOR_IDLE_LOWBAT_TIME   8 * HAL_TICK1S    /*15 * HAL_TICK1S */
#define PM_BAT_MONITOR_IDLE_CRITICAL_TIME  1 * HAL_TICK1S /*5 * HAL_TICK1S */

/* Number of debounce for the ear detect */
#define PM_AVERAGE_EAR_NB       10
#define PM_BATTERY_DETECT_INTERVAL 3620

typedef struct {
    /*/ sum the battery measures */
    uint32_t sum;
    /*/ calculated mean level */
    uint16_t avg;
    /*/ histeresys stable value */
    uint16_t stable;
    /*/ last instant value */
    uint16_t instant;
    /*/ array of measures to maintaint the mean */
    uint16_t levels[PM_AVERAGE_BATTERY_NB];
    /*/ current index in the array */
    uint8_t idx;
    /*/ number of measures (for init) */
    uint8_t nb;
    /*/ calculated percent from the stable value */
    uint8_t percent;
} PM_BATTERY_STABLE_T;

typedef struct {
    uint8_t mode;
    BOOL earon;
    BOOL gpadcMonStarted;
    BOOL gpadcMonDisabled;
} PM_EAR_DETECT_T;

static PM_BATTERY_STABLE_T g_pmBatteryStable;

/*/ battery monitoring perriod */
static uint32_t g_pmBatMonTime = PM_BAT_MONITOR_IDLE_TIME;
static uint32_t g_pmBatMonLastDate = 0;
/*/ earpiece detect perriod */
static uint8_t g_pmChargeFlag = 0;
//static uint8_t g_pmRemindTime = 0;
/* added private funtion to do the job with pmd */
static uint8_t g_pm_powerdowervolt = 0;

static PMIC_CHARGER_STATUS_T g_pm_oldStatus = PMIC_CHARGER_UNKNOWN;

uint8_t charger_present = 0;

static BOOL charger_status_is_usb = FALSE;
//BOOL Battery_charge_full = FALSE;
//static int is_bootup_standby = 0;
static Usb_PlugCallback Send_usb_status = NULL;
static Sim_CallCallback Get_call_status = NULL;
static Battery_Callback Send_battery_status = NULL;

extern PMIC_CHARGE_EVENT_T charger_event;
extern PMIC_CHARGER_STATE_T g_pmicChargerState;

const PMIC_CONFIG_T *g_pmicConfig;

static uint16_t ChangeVoltageToBatteryRate(uint8_t *pPercent);

BOOL ChargerCallbackRegister(Usb_PlugCallback Usb_charger_status, Sim_CallCallback get_call_status, Battery_Callback battery_status)
{
    chargerCfgGetSetting();
    if(!Usb_charger_status || !get_call_status || !battery_status) {
        printf("Error: ChargerCallbackRegister : call back function is NULL!\n");
        return FALSE;
    }
    Send_usb_status = Usb_charger_status;
    Get_call_status = get_call_status;
    Send_battery_status = battery_status;

    return TRUE;
}
/*/ @param status to convert */
/*/ @return Bcs value */
static uint8_t pm_PmdChargerStatus2Bcs(PMIC_CHARGER_STATUS_T status)
{
    uint8_t bcs;
    bcs = PM_CHARGER_CONNECTED;

    /* always go to the step 'connected' before any charge step */
    if((g_pm_oldStatus <= PMIC_CHARGER_UNPLUGGED)
       && (status > PMIC_CHARGER_UNPLUGGED)) {
      g_pm_oldStatus = PMIC_CHARGER_PLUGGED;
      return bcs;
    }
    g_pm_oldStatus = status;

    switch(status) {
    case PMIC_CHARGER_UNKNOWN:
    case PMIC_CHARGER_UNPLUGGED:
      bcs = PM_CHARGER_DISCONNECTED;
      break;
    case PMIC_CHARGER_PLUGGED:
      bcs = PM_CHARGER_CONNECTED;
      break;
    case PMIC_CHARGER_PRECHARGE:
    case PMIC_CHARGER_FAST_CHARGE:
    case PMIC_CHARGER_PULSED_CHARGE:
    case PMIC_CHARGER_PULSED_CHARGE_WAIT:
      bcs = PM_CHARGER_CHRGING;
      break;
    case PMIC_CHARGER_FULL_CHARGE:
      bcs = PM_CHARGER_FINISHED;
      break;
    case PMIC_CHARGER_TEMPERATURE_ERROR:
      bcs = PM_CHARGER_ERROR_TEMPERATURE;
      break;
    case PMIC_CHARGER_VOLTAGE_ERROR:
      bcs = PM_CHARGER_ERROR_VOLTAGE;
      break;
    case PMIC_CHARGER_ERROR:
    case PMIC_CHARGER_TIMED_OUT:
    default:
      bcs = PM_CHARGER_ERROR_UNKNOWN;
      break;
    }
    return bcs;
}

static BOOL pm_BatteryLevel2State(uint16_t batLevel, uint8_t *pBcl, uint16_t *pBatState)
{
    if((pBcl == NULL) || (pBatState == NULL)) {
        return FALSE;
    }
    if(batLevel == PMIC_BAD_VALUE) {
        *pBcl = 0;
        *pBatState = PM_BATTERY_STATE_UNKNOWN;
    } else {
        if(*pBcl == 0) {
          /*           *pBcl      = 1; */
          *pBatState = PM_BATTERY_STATE_SHUTDOWN;
        } else {
          /*/ @todo: not hardcode levels */
          if(*pBcl < g_pm_powerdowervolt) {      /* if (*pBcl < 20) */
            *pBatState = PM_BATTERY_STATE_SHUTDOWN;
          } else if(*pBcl < (g_pm_powerdowervolt + 5)) {   /*if (*pBcl < 25) */
            *pBatState = PM_BATTERY_STATE_CRITICAL;
          } else if(*pBcl < (g_pm_powerdowervolt + 10)) {   /*if (*pBcl < 30) */
            *pBatState = PM_BATTERY_STATE_LOW;
          } else {
            *pBatState = PM_BATTERY_STATE_NORMAL;
          }
        }
        /*  *pBatState = PM_BATTERY_STATE_NORMAL; // only use the narmal status. */
    }

    return TRUE;
}

static int pm_GetStableBatteryLevel(uint8_t *pPercent)
{
    uint8_t bcl = 0, i = 0;
    uint8_t avgPercent;
    int16_t batLevelTemp1 = 0, batLevelTemp2 = 0;

    uint16_t batLevel = pmic_GetBatteryLevel(&bcl);

    if(batLevel == PMIC_BAD_VALUE) {
      printf("pm:  PMIC_BAD_VALUE");
      return PMIC_BAD_VALUE;
    }
    if(batLevel < 2000) {
      printf("pm:  PMIC_BAD_VALUE too small\n");
      return PMIC_BAD_VALUE;
    }

    if(g_pmBatteryStable.nb == PM_AVERAGE_BATTERY_NB) {
      if(g_pmBatteryStable.avg > batLevel) {
        if((g_pmBatteryStable.avg - batLevel) > PM_FILTRATE_BATTERY_STEP) {
          printf("pm:  too small %dmv", batLevel);
          return PMIC_BAD_VALUE;
        }
      }
    }

    if(g_pmBatteryStable.avg > batLevel + PM_RF_TX_BATTERY_STEP) {
      uint32_t callStatus = 0x00;
#ifdef CMID_MULTI_SIM
      CMID_SIM_ID nSimId;
      for(nSimId = CMID_SIM_0; nSimId < CMID_SIM_COUNT; nSimId++) {
        if(Get_call_status) {
          callStatus |= Get_call_status(nSimId);
        }
      }
#else
      if(Get_call_status) {
        callStatus |= Get_call_status(0);
      }
#endif

      if(callStatus != 0) {     /* not in CC_STATE_NULL */
        /* The battery level might be measured at the time RF was transmitting (PA was working). */
        /* Try to compensate the instant battery level drop. */
        batLevel = (uint16_t)(batLevel / 8 + (uint32_t)g_pmBatteryStable.avg * 7 / 8);
      }
    }

    g_pmBatteryStable.sum -= g_pmBatteryStable.levels[g_pmBatteryStable.idx];
    g_pmBatteryStable.sum += batLevel;
    g_pmBatteryStable.levels[g_pmBatteryStable.idx] = batLevel;
    if(g_pmBatteryStable.nb < PM_AVERAGE_BATTERY_NB) {
      g_pmBatteryStable.nb++;
    }
    g_pmBatteryStable.idx++;
    if(g_pmBatteryStable.idx >= PM_AVERAGE_BATTERY_NB) {
      g_pmBatteryStable.idx = 0;
    }
    /*..... */
    if(g_pmBatteryStable.nb > 10) {
      batLevelTemp1 = g_pmBatteryStable.levels[0];
      for(i = 0; i < g_pmBatteryStable.nb; i++) {
        if(batLevelTemp1 > g_pmBatteryStable.levels[i]) {
          batLevelTemp1 = g_pmBatteryStable.levels[i];
        }
      }
      batLevelTemp2 = g_pmBatteryStable.levels[0];
      for(i = 0; i < g_pmBatteryStable.nb; i++) {
        if(batLevelTemp2 < g_pmBatteryStable.levels[i]) {
          batLevelTemp2 = g_pmBatteryStable.levels[i];
        }
      }
      batLevelTemp1 += batLevelTemp2;
      g_pmBatteryStable.avg = (g_pmBatteryStable.sum - batLevelTemp1) / (g_pmBatteryStable.nb - 2);
    } else {
      g_pmBatteryStable.avg = g_pmBatteryStable.sum / g_pmBatteryStable.nb;
    }
    g_pmBatteryStable.instant = batLevel;
  /*    g_pmBatteryStable.avg = g_pmBatteryStable.sum / g_pmBatteryStable.nb; */
    /* hysteresis leveling: */
    if((((INT32)g_pmBatteryStable.stable - (INT32)g_pmBatteryStable.avg)
        >= PM_HYSTERESIS_BATTERY_STEP)
       || (((INT32)g_pmBatteryStable.avg - (INT32)g_pmBatteryStable.stable)
           >= PM_HYSTERESIS_BATTERY_STEP)) {
      g_pmBatteryStable.stable = g_pmBatteryStable.avg;
    }
    /* forcing hysteresis for the last few % (near 0% and 100%) */
    avgPercent = pmic_BatteryLevelToPercent(g_pmBatteryStable.avg);
    if((avgPercent <= PM_HYSTERESIS_BATTERY_PERCENT_EDGE + 13)
       || (avgPercent >= (100 - PM_HYSTERESIS_BATTERY_PERCENT_EDGE))) {
      g_pmBatteryStable.stable = g_pmBatteryStable.avg;
    }

    /* calculate %, print and return value... */
    g_pmBatteryStable.percent = pmic_BatteryLevelToPercent(g_pmBatteryStable.stable);
    if(pPercent != NULL) {
      *pPercent = g_pmBatteryStable.percent;
    }
    printf("pm: instant: %dmV, %d%%; mean: %dmV, %d%%; stable: %dmV, %d%%\n",
                     batLevel, bcl, g_pmBatteryStable.avg, avgPercent, g_pmBatteryStable.stable, g_pmBatteryStable.percent);

    return g_pmBatteryStable.stable;
}

BOOL pm_BattChargeRemind(PMIC_CHARGER_STATUS_T status)
{
    uint8_t bcl = 0;
    uint8_t bcs = 0;
    uint16_t batState = 0;
    uint16_t batLevel = 0;
    if(g_pmChargeFlag == 1) {
      batLevel = g_pmBatteryStable.stable;
      bcl = g_pmBatteryStable.percent;
      if(status == PMIC_CHARGER_PLUGGED) {
        bcs = PM_CHARGER_CONNECTED;
      } else {
        bcs = PM_CHARGER_DISCONNECTED;
      }
    } else {
      printf("pm_BattChargeRemind : Has_battery_discharger_table : %d\n", g_pmicConfig->Has_battery_discharger_table);
      if(g_pmicConfig->Has_battery_discharger_table) {
        batLevel = ChangeVoltageToBatteryRate(&bcl);
      } else {
        batLevel = pm_GetStableBatteryLevel(&bcl);
      }
      printf("pm_BattChargeRemind : batLevel : %d\n", batLevel);
      if((g_pm_oldStatus == PMIC_CHARGER_FULL_CHARGE) && (status == PMIC_CHARGER_FULL_CHARGE)) {
        printf("pm: Remind Full charge not reporting to MMI anymore Bcl=%d%%, batLevel=%dmV\n", bcl, batLevel);
        return TRUE;
      }
      if((g_pm_oldStatus == PMIC_CHARGER_TIMED_OUT) && (status == PMIC_CHARGER_TIMED_OUT)) {
        printf("pm: Remind timeout charge not reporting to MMI anymore Bcl=%d%%, batLevel=%dmV\n", bcl, batLevel);
        return TRUE;
      }
      if((batLevel == PMIC_BAD_VALUE) || (batLevel < 2000)) {
        printf("pm: Remind PMIC_BAD_VALUE\n");
        return FALSE;
      }
      bcs = pm_PmdChargerStatus2Bcs(status);

      /* force histeresys to 100% when charge is full */
      switch(status) {
      case PMIC_CHARGER_FULL_CHARGE:
      {
        g_pmBatteryStable.stable = g_pmBatteryStable.avg;
        g_pmBatteryStable.percent = 100;
        bcl = 100;
      }
      break;
      case PMIC_CHARGER_PLUGGED:
      case PMIC_CHARGER_PRECHARGE:
      case PMIC_CHARGER_FAST_CHARGE:
      case PMIC_CHARGER_PULSED_CHARGE:
      case PMIC_CHARGER_PULSED_CHARGE_WAIT:
      {
#ifndef For_Watch_Battery
        if(bcl > 99) {
          g_pmBatteryStable.percent = 99;
          bcl = 99;
        }
#endif
      }
      break;
      default:
        break;
      }
      printf("pm: Remind Bcs=%d, Bcl=%d%%, batState=%d, stable_volt=%dmV\n", bcs, bcl, batState, batLevel);
    }
    if(Send_battery_status) {
      if(batLevel <= 3400) {
        bcl = 0;       /*for watch */
      }
      Send_battery_status(bcs, bcl, batLevel);
      printf("Send_battery_status : bcs = %d, bcl = %d, batLevel = %d \n", bcs, bcl, batLevel);
    }
    return TRUE;
}

void pm_ChargerHandler(void)
{
    PMIC_CHARGER_STATUS_T status;
  /*  raw_uart_log("charger interrupt cnt:%d\n",charger_cnt++); */
  /*  UOS_Sleep(6);//wait 30ms for usb_shutdown status updata */
    if(CommPMVbusDetect()) {
      printf("pm_ChargerHandler :charger in\n");
      charger_event = PMIC_CHARGE_DC_ON;
      status = PMIC_CHARGER_PLUGGED;
      charger_present = 1;
#if For_Watch_Battery
      charger_status_is_usb = TRUE;
      if(Send_usb_status) {
        Send_usb_status(1);
      }
#endif
    } else {
      charger_event = PMIC_CHARGE_DC_OFF;
      status = PMIC_CHARGER_UNPLUGGED;
      charger_present = 0;
      printf("pm_ChargerHandler :charger out\n");
      if(charger_status_is_usb) {
        if(Send_usb_status) {
          Send_usb_status(0);
        }
        charger_status_is_usb = FALSE;
      }
    }
    g_pmicChargerState.status = status;
    g_pmChargeFlag = 1;
    pm_BattChargeRemind(status);
    g_pmChargeFlag = 0;
}

static void pm_doMonitoring(BOOL fromLowPowerEvent)
{
    uint32_t now;
    uint32_t callStatus;
    uint16_t batState, batLevel;
    uint8_t bcl;
    PMIC_CHARGER_STATUS_T status;
    now = get_time_ms();
    if((now - g_pmBatMonLastDate) >= g_pmBatMonTime) {
      /* monitor battery & charger and tell mmi */
      status = pmic_GetChargerStatus();
      if(pm_BattChargeRemind(status)) {
        /* successful, record it */
        g_pmBatMonLastDate = now;
      }
    }
    callStatus = 0x00;
    batLevel = g_pmBatteryStable.instant;
    bcl = pmic_BatteryLevelToPercent(batLevel);
    pm_BatteryLevel2State(batLevel, &bcl, &batState);
    if(fromLowPowerEvent) {
      /* called from lp event, assuming not in call then ;) */
    } else {
#ifdef CMID_MULTI_SIM
      CMID_SIM_ID nSimId;
      for(nSimId = CMID_SIM_0; nSimId < CMID_SIM_COUNT; nSimId++) {
        if(Get_call_status) {
          callStatus |= Get_call_status(nSimId);
        }
      }
#else
      if(Get_call_status) {
        callStatus |= Get_call_status(0);
      }
#endif
    }

    if(callStatus == 0 /*CC_STATE_NULL*/) { /* not in call */
      if(batState == PM_BATTERY_STATE_LOW) {
        g_pmBatMonTime = PM_BAT_MONITOR_IDLE_LOWBAT_TIME;
      } else if((batState == PM_BATTERY_STATE_CRITICAL) || (batState == PM_BATTERY_STATE_SHUTDOWN)) {
        g_pmBatMonTime = PM_BAT_MONITOR_IDLE_CRITICAL_TIME;
      } else {
        g_pmBatMonTime = PM_BAT_MONITOR_IDLE_TIME;
      }
#if 0
      else if(batState == PM_BATTERY_STATE_SHUTDOWN) {
        g_pmBatMonTime = PM_BAT_MONITOR_IDLE_CRITICAL_TIME;
      } else {
        if(g_pmBatteryStable.stable > PM_BATTERY_DETECT_INTERVAL) {
          g_pmBatMonTime = PM_BAT_MONITOR_IDLE_TIME;
        } else {
          g_pmBatMonTime = PM_BAT_MONITOR_IDLE_LOWBAT_TIME;
        }
      }
#endif
    } else { /* in call */
      if((batState == PM_BATTERY_STATE_CRITICAL) || (batState == PM_BATTERY_STATE_SHUTDOWN)) {
        g_pmBatMonTime = PM_BAT_MONITOR_IDLE_CRITICAL_TIME;
      } else {
        g_pmBatMonTime = PM_BAT_MONITOR_CALL_TIME;
      }
    }

    Time_To_MMI_Evt = g_pmBatMonTime;
}

BOOL pm_BatteryInit(VOID)
{
    uint32_t now;

    now = get_time_ms();
    pmic_InitCharger();
    Time_To_MMI_Evt = g_pmBatMonTime;
    g_pmBatMonLastDate = now - g_pmBatMonTime;
    /*/ shutdown if battery too low & no charger */
    {
      uint16_t batLevel = PMIC_BAD_VALUE;
      uint8_t bcl = 40;
      PMIC_CHARGER_STATUS_T status = PMIC_CHARGER_UNKNOWN;
      g_pm_powerdowervolt = pmic_GetPowerDownVolt();

      /* wait for a valid charger detection and valid battery measurement */
      while((batLevel == PMIC_BAD_VALUE) || (status == PMIC_CHARGER_UNKNOWN)) {
        status = pmic_GetChargerStatus();
        batLevel = pmic_GetBatteryLevel(&bcl);
        printf("pm_BatteryInit: batLevel: %d, percent: %d \n", batLevel, bcl);
      }
    }
    /* Initiate charger status */
#ifdef For_Watch_Battery
  //  if(CommPMVbusDetect()) {
      pm_ChargerHandler();
  //  }
#endif
    /* register the charger handler to get charger event faster */
    USB_WAKEUP_CALLBACK_REGISTER(pm_ChargerHandler);
    return TRUE;
}

BOOL pm_BatteryMonitorProc(void)
{
/*    unsigned int start_us,cost_us; */
/*    start_us = get_usec(); */
    if(charger_present) {
      ChargerManager();
    }
    pm_doMonitoring(FALSE);
/*    cost_us = get_usec() - start_us; */
/*  raw_uart_log("!!!!Battery monitor cost:%d\n",cost_us); */
/*    UOS_Sleep(MS_TO_TICKS(Time_To_MMI_Evt)); */
  return 1;
}

BOOL IsBatteryInCharge(void)
{
    return charger_present;
}

uint16_t GetAverageBatteryLevel(void)
{
    uint16_t uVoltage = pmic_GetGpadcBatteryLevel();
    g_pmBatteryStable.instant = uVoltage;
    if(uVoltage == PMIC_BAD_VALUE) {
      printf("Error : pm:  GetAverageBatteryLevel PMIC_BAD_VALUE!! \n");
      return PMIC_BAD_VALUE;
    }
    if(uVoltage < 2000) {
      printf("Error : pm:  GetAverageBatteryLevel too small\n");
      return PMIC_BAD_VALUE;
    }

    if(g_pmBatteryStable.avg > uVoltage + PM_RF_TX_BATTERY_STEP) {
      uint32_t callStatus = 0x00;
      if(Get_call_status) {
        callStatus |= Get_call_status(0);
        printf("pm : callstatus: %d \n", callStatus);
      }

      if((callStatus != 0) && (pmic_BatteryLevelToPercent(uVoltage) > 20)) {     /* not in CC_STATE_NULL */
        uVoltage = (uint16_t)(uVoltage / 8 + (uint32_t)g_pmBatteryStable.avg * 7 / 8);
      }
    }
    if(g_pmBatteryStable.nb >= PM_AVERAGE_BATTERY_NB) {
      g_pmBatteryStable.sum -= g_pmBatteryStable.levels[g_pmBatteryStable.idx];
      g_pmBatteryStable.sum += uVoltage;
      g_pmBatteryStable.avg = g_pmBatteryStable.sum / PM_AVERAGE_BATTERY_NB;
    } else {
      g_pmBatteryStable.sum += uVoltage;
      g_pmBatteryStable.nb++;
      g_pmBatteryStable.avg = g_pmBatteryStable.sum / g_pmBatteryStable.nb;
    }
    g_pmBatteryStable.levels[g_pmBatteryStable.idx] = uVoltage;
    g_pmBatteryStable.idx++;
    if(g_pmBatteryStable.idx >= PM_AVERAGE_BATTERY_NB) {
      g_pmBatteryStable.idx = 0;
    }
    g_pmBatteryStable.stable = g_pmBatteryStable.avg;
    printf("pm : GetAverageBatteryLevel : %d\n", g_pmBatteryStable.avg);
    return g_pmBatteryStable.avg;
}

unsigned char g_LastBatteryRate = 0;

uint16_t ChangeVoltageToBatteryRate(uint8_t *pPercent)
{
    uint16_t uVoltage = 0;
    unsigned char curBatteryRate = 0;
    int i = 0;

    uVoltage = GetAverageBatteryLevel();

    if(uVoltage >= g_pmicConfig->BatteryDischarger_table[0]) {
      curBatteryRate = 100;
    } else if(uVoltage < g_pmicConfig->BatteryDischarger_table[100]) {
      curBatteryRate = 0;
    } else {
      if(charger_present) {/*?? */
        for(i = 1; i < (101 - g_LastBatteryRate); i++) {
          if(uVoltage < g_pmicConfig->BatteryDischarger_table[i - 1] && uVoltage >= g_pmicConfig->BatteryDischarger_table[i]) {
            curBatteryRate = 100 - i;

            printf("Charging Current_vol = %d, pre = %d\r\n", curBatteryRate, g_LastBatteryRate);
#ifdef For_Watch_Battery
            if((curBatteryRate > g_LastBatteryRate) && ((curBatteryRate - g_LastBatteryRate) > 15)) {
              printf("Battery dif is bigger than 15, dif: %d, will use new value.\r\n", (curBatteryRate - g_LastBatteryRate));
            } else {
              if(curBatteryRate < g_LastBatteryRate) {
                curBatteryRate = g_LastBatteryRate;
              } else if(curBatteryRate > g_LastBatteryRate + 1 && g_LastBatteryRate != 0) {
                curBatteryRate = g_LastBatteryRate + 1;
              }
            }
#endif
            break;
          }
        }

        if(i == (101 - g_LastBatteryRate)) {
#ifdef For_Watch_Battery
          curBatteryRate = g_LastBatteryRate;
#else
          for(i = 101 - g_LastBatteryRate; i < 101; i++) { /*when battery full charger off */
            if(uVoltage < g_pmicConfig->BatteryDischarger_table[i - 1] && uVoltage >= g_pmicConfig->BatteryDischarger_table[i]) {
              curBatteryRate = 100 - i;
              printf("Battery Charging Current_vol = %d, pre = %d\r\n", curBatteryRate, g_LastBatteryRate);
              break;
            }
          }
#endif
        }
      } else {/*?? */
        int j = 0;
        if((g_LastBatteryRate > 0) && (g_LastBatteryRate <= 100)) {
          j = 100 - g_LastBatteryRate;
        } else {
          j = 1;
        }

        for(i = j; i < 101; i++) {
          if(uVoltage < g_pmicConfig->BatteryDischarger_table[i - 1] && uVoltage >= g_pmicConfig->BatteryDischarger_table[i]) {
            curBatteryRate = 100 - i;

            printf("Discharging Current_vol = %d, pre = %d\r\n", curBatteryRate, g_LastBatteryRate);
#ifdef For_Watch_Battery
            if(g_LastBatteryRate > 0) {
              if(curBatteryRate > g_LastBatteryRate) {
                if(curBatteryRate - g_LastBatteryRate <= 30) {
                  curBatteryRate = g_LastBatteryRate;
                } else {
                  printf("Discharging Current_vol = %d error!!!\r\n", curBatteryRate);
                }
              } else if(curBatteryRate < g_LastBatteryRate - 1) {
                curBatteryRate = g_LastBatteryRate - 1;
              }
            }
#endif
            break;
          }
        }
        if(i == 101) {
          curBatteryRate = g_LastBatteryRate;
        }
      }
    }

  /*  raw_uart_log("convert_cur_battery_percent g_curr_vol = %d\r\n", curBatteryRate); */
#ifdef For_Watch_Battery
    if(charger_present) {/*charging */
      if(curBatteryRate > 95) {
        curBatteryRate = 95;
      }
    }
#endif
  /*    raw_uart_log("Stable battery level = %d\r\n", curBatteryRate); */
    g_LastBatteryRate = curBatteryRate;
    if(pPercent != NULL) {
      *pPercent = curBatteryRate;
    }
    g_pmBatteryStable.percent = curBatteryRate;
    return uVoltage;
}

uint32_t charger_get_Time_To_MMI_Evt(void)
{
    return Time_To_MMI_Evt;
}
#endif
